package com.smartfactory.sail.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smartfactory.sail.dto.GetItemAndMaterialSizeDto;
import com.smartfactory.sail.entity.*;
import com.smartfactory.sail.entity.enums.*;
import com.smartfactory.sail.mapper.PurchaseMapper;
import com.smartfactory.sail.mapper.PurchaseRecordMapper;
import com.smartfactory.sail.service.*;
import com.smartfactory.sail.utils.CodeUtils;
import com.smartfactory.sail.utils.DateUtils;
import com.smartfactory.sail.utils.PageUtils;
import com.smartfactory.sail.vo.PageParam;
import com.smartfactory.sail.vo.purchase.ListPurchaseResp;
import com.smartfactory.sail.vo.statics.IndexDHTXVo;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 采购单表 服务实现类
 * </p>
 *
 * @author 王巨壁
 * @since 2019-08-20
 */
@Service
public class PurchaseServiceImpl extends ServiceImpl<PurchaseMapper, Purchase> implements IPurchaseService {

    private PurchaseMapper purchaseMapper;

    private IOrderItemService iOrderItemService;
    private IPurchaseRecordService iPurchaseRecordService;
    private IStorageCurrentInfoService iStorageCurrentInfoService;
    private IItemService iItemService;
    private IStorageRecordService iStorageRecordService;
    private PurchaseRecordMapper purchaseRecordMapper;
    private IOrderService iOrderService;

    public PurchaseServiceImpl(PurchaseMapper purchaseMapper, IOrderItemService iOrderItemService, IPurchaseRecordService iPurchaseRecordService, IStorageCurrentInfoService iStorageCurrentInfoService, IItemService iItemService, IStorageRecordService iStorageRecordService, PurchaseRecordMapper purchaseRecordMapper, IOrderService iOrderService) {
        this.purchaseMapper = purchaseMapper;
        this.iOrderItemService = iOrderItemService;
        this.iPurchaseRecordService = iPurchaseRecordService;
        this.iStorageCurrentInfoService = iStorageCurrentInfoService;
        this.iItemService = iItemService;
        this.iStorageRecordService = iStorageRecordService;
        this.purchaseRecordMapper = purchaseRecordMapper;
        this.iOrderService = iOrderService;
    }

    @Override
    public IPage<ListPurchaseResp> getListByPage(Map<String, Object> queryParam, PageParam pageParam) {

        //分页信息
        Page<ListPurchaseResp> page = new Page<>();
        PageUtils.createPage(page, pageParam);

        QueryWrapper<ListPurchaseResp> query = new QueryWrapper<>();
        query.allEq(queryParam);
        return purchaseMapper.getListByPage(page, query);
    }

    /**
     * 将可分配数量分配至合同订单绑定数量
     *
     * @param itemId
     * @param getAllocate 需要分配到绑定的字段的原料数
     */
    private void allocate(long itemId, Integer getAllocate) {
        if (getAllocate > 0) {
            StorageCurrentInfo currentInfo = iStorageCurrentInfoService.getOne(new LambdaQueryWrapper<StorageCurrentInfo>().eq(StorageCurrentInfo::getItemId, itemId));
            Integer allocatableSize = currentInfo.getAllocatableSize();
            Integer size = currentInfo.getSize();
            currentInfo.setAllocatableSize(allocatableSize - getAllocate);
            currentInfo.setSize(size + getAllocate);
            iStorageCurrentInfoService.updateById(currentInfo);
        }
    }

    private void recursion(long orderId, Map<Long, List<GetItemAndMaterialSizeDto>> items, List<PurchaseRecord> purchaseRecords) {
        items.forEach((itemId, sizeDtos) -> {
            boolean canPro = true;
            for (GetItemAndMaterialSizeDto sizeDto : sizeDtos) {
                //当前库存
                int currentSize = sizeDto.getAllocatableSize();
                //需要生产的产品数
                Integer productSize = sizeDto.getProductSize();
                //每个产品需要该原料的数量
                Integer materialSize = sizeDto.getMaterialSize() * sizeDto.getPickingRate() / 100;
                //需要的原料总数
                int totalSize = materialSize * productSize;

                if (sizeDto.getStorageType().equals(StorageType.CPK)) {
                    currentSize = 0;
                    int getAllocate;
                    if (totalSize > currentSize) {
                        int needProduct = totalSize - currentSize;
                        getAllocate = currentSize;
                        //这种情况需要自己生产 递归调用
                        Long materialId = sizeDto.getMaterialId();

                        OrderItem currentOrderItem = iOrderItemService.findByOrderIdAndItemId(itemId, orderId);
                        OrderItem orderItem = new OrderItem();
                        BeanUtils.copyProperties(currentOrderItem, orderItem);

                        Item item = iItemService.getById(materialId);
                        BeanUtils.copyProperties(item, orderItem);
                        orderItem.setId(null);
                        orderItem.setItemId(materialId);
                        orderItem.setSize(needProduct);
                        orderItem.setPurpose(2);//该订单  用于生产 .

                        iOrderItemService.save(orderItem);
                        List<GetItemAndMaterialSizeDto> itemAndMaterialSize = purchaseMapper.getItemAndMaterialSize(orderId);
                        Map<Long, List<GetItemAndMaterialSizeDto>> one = itemAndMaterialSize.stream().filter(dto -> dto.getProductId().equals(materialId)).collect(Collectors.groupingBy(GetItemAndMaterialSizeDto::getProductId, Collectors.toList()));
                        recursion(orderId, one, purchaseRecords);
                    } else {
                        getAllocate = totalSize;
                    }
                    allocate(itemId, getAllocate);
                } else if (sizeDto.getStorageType().equals(StorageType.YLK)) {
                    int getAllocate;
                    if (totalSize > currentSize) {
                        int needPurchase = totalSize - currentSize;
                        getAllocate = currentSize;
                        Long materialId = sizeDto.getMaterialId();
                        Item item = iItemService.getById(materialId);
                        //获取上次采购价格
                        BigDecimal lastPrice = purchaseRecordMapper.getLastPrice(materialId);
                        PurchaseRecord purchaseRecord = new PurchaseRecord();
                        if (lastPrice != null) {
                            purchaseRecord.setLastPrice(lastPrice);
                        }
                        purchaseRecord.setCurrentStorageSize(currentSize);
                        purchaseRecord.setPurchaseSize(needPurchase);
                        purchaseRecord.setItemId(materialId);
                        purchaseRecord.setItemName(item.getName());
                        purchaseRecord.setItemCode(item.getCode());
                        purchaseRecord.setSpecification(sizeDto.getSpecification());
                        purchaseRecords.add(purchaseRecord);
                    } else {
                        getAllocate = totalSize;
                    }

                    allocate(itemId, getAllocate);
                }

                if (materialSize > currentSize) {
                    canPro = false;
                }
            }
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(orderId);
            orderItem.setItemId(itemId);
            if (canPro)
                //库存满足  可以分配
                orderItem.setStatus(OrderItemStatusEnum.DFP);
            else
                orderItem.setStatus(OrderItemStatusEnum.YLBZ);
            iOrderItemService.updateStatus(orderItem);
            LambdaQueryWrapper<OrderItem> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(OrderItem::getOrderId, orderId);
            List<OrderItem> list = iOrderItemService.list(queryWrapper);
            boolean flag = true;
            for (OrderItem item : list) {
                if (item.getStatus().equals(OrderItemStatusEnum.DPB)) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                Order order = iOrderService.getById(orderId);
                order.setStatus(OrderStatusEnum.SCZ);
                iOrderService.updateById(order);
            }
        });
    }

    /**
     * 处理新增合同订单的采购事务
     *
     * @param orderId
     */
    @Override
    @Async
    public void orderPurChaseHandle(Long orderId, long itemId) {
        //订单中需要产品的数量   生产产品需要的原料数量
        List<GetItemAndMaterialSizeDto> itemAndMaterialSize = purchaseMapper.getItemAndMaterialSize(orderId);
        Map<Long, List<GetItemAndMaterialSizeDto>> items = itemAndMaterialSize.stream().filter(sizeDto -> sizeDto.getProductId().equals(itemId)).collect(Collectors.groupingBy(GetItemAndMaterialSizeDto::getProductId, Collectors.toList()));
        List<PurchaseRecord> purchaseRecords = new ArrayList<>();
        recursion(orderId, items, purchaseRecords);
        if (!purchaseRecords.isEmpty()) {
            Purchase purchase = new Purchase();
            purchase.setPurchaseType(PurchaseTypeEnum.HTDD);
            purchase.setObjId(orderId);
            purchase.setStatus(PurchaseStatusEnum.DCG);
            purchase.setCode(CodeUtils.creatCGCode());
            save(purchase);
            Long purchaseId = purchase.getId();
            purchaseRecords.forEach(purchaseRecord -> {
                purchaseRecord.setPurchaseId(purchaseId);
                purchaseRecord.setStatus(PurchaseStatusEnum.DCG);//待采购
                iPurchaseRecordService.save(purchaseRecord);

                StorageRecord storageRecord = new StorageRecord();
                storageRecord.setStorageType(StorageType.YLK);
                storageRecord.setItemId(purchaseRecord.getItemId());
                storageRecord.setPurchaseRecordId(purchaseRecord.getId());
                storageRecord.setSize(purchaseRecord.getPurchaseSize());
                storageRecord.setStatus(StorageStatusEnum.DRK);

                iStorageRecordService.save(storageRecord);
            });
        }
    }

    /**
     * 查询采购提醒
     *
     * @return
     */
    public List<IndexDHTXVo> indexDHTX() {
        LambdaQueryWrapper<PurchaseRecord> query = new LambdaQueryWrapper<>();
        query.eq(PurchaseRecord::getStatus, PurchaseStatusEnum.CGZ);
        List<PurchaseRecord> purchaseRecords = purchaseRecordMapper.selectList(query);
        ArrayList<IndexDHTXVo> vos = new ArrayList<>();
        for (PurchaseRecord purchaseRecord : purchaseRecords) {
            //预计到货时间
            String arrivalTime = purchaseRecord.getArrivalTime();
            //提前几天提醒
            Integer reminderDays = purchaseRecord.getReminderDays();
            Long diffDays = DateUtils.dayDiff(DateUtils.getNowDate(), arrivalTime);

            IndexDHTXVo vo = new IndexDHTXVo();
            BeanUtils.copyProperties(purchaseRecord, vo);
            if (diffDays == 0) {
                vo.setMsg("预计今日到货");
                vo.setStatuCode(0);
            } else if (diffDays < 0) {
                vo.setMsg("已超出预期" + Math.abs(diffDays) + "天");
                vo.setStatuCode(-1);
            } else {
                if (diffDays <= reminderDays) {
                    vo.setMsg("预计还有" + diffDays + "天到货");
                    vo.setStatuCode(1);
                }
            }
            vos.add(vo);
        }
        return vos;
    }

}
